// -----------------------------------------------------------------------
//  <copyright file="DataAuthorizationService.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2025 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2025-02-27 19:02</last-date>
// -----------------------------------------------------------------------

using DaprPlus.Dependency;
using DaprPlus.Filters;
using DaprPlus.Properties;


namespace DaprPlus.Authorization;

public class DataAuthorizationService : IDataAuthorizationService
{
    private readonly ILogger _logger;
    private readonly ScopedDictionary _scopedDict;
    private readonly IFilterService _filterService;

    public DataAuthorizationService(IServiceProvider provider)
    {
        _logger = provider.GetLogger(GetType());
        _scopedDict = provider.GetRequiredService<ScopedDictionary>();
        _filterService = provider.GetRequiredService<IFilterService>();
    }

    /// <summary>
    /// 应用数据过滤条件到查询
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    /// <param name="query">原始查询</param>
    /// <returns>应用过滤条件后的查询</returns>
    public IQueryable<T> ApplyDataFilters<T>(IQueryable<T> query) where T : class
    {
        // 检查是否需要忽略数据权限验证
        if (_scopedDict.IgnoreDataAuthTypes.Contains(typeof(T)))
        {
            return query;
        }

        var filterGroup = _scopedDict.GetFilterGroup(DataOperation.Read);
        if (filterGroup == null || filterGroup.IsEmpty() || filterGroup.TargetEntityType != typeof(T).FullName)
        {
            return query;
        }

        try
        {
            // 将过滤条件组转换为表达式
            var expression = _filterService.GetExpression<T>(filterGroup);

            // 应用表达式到查询
            var filteredQuery = query.Where(expression);
            return filteredQuery;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, ResDaprPlus.Format_DataAuth_ApplyFilterError, typeof(T).Name);
            // 发生错误时返回原始查询
            return query;
        }
    }

    /// <summary>
    /// 检查单个或多个实体是否符合数据权限
    /// </summary>
    /// <typeparam name="T">实体类型</typeparam>
    /// <param name="dataOperation">数据操作类型</param>
    /// <param name="datas">要检查的实体数组</param>
    /// <returns>是否符合数据权限</returns>
    public bool CheckEntityAccess<T>(DataOperation dataOperation, params T[] datas) where T : class
    {
        if (datas.Length == 0)
        {
            return false;
        }

        var filterGroup = _scopedDict.GetFilterGroup(dataOperation);
        if (filterGroup == null || filterGroup.IsEmpty() || filterGroup.TargetEntityType != typeof(T).FullName)
        {
            // 没有过滤条件，默认允许访问
            return true;
        }

        // 将过滤条件组转换为表达式
        var expression = _filterService.GetExpression<T>(filterGroup);

        try
        {
            var predicate = expression.Compile();

            // 检查所有实体是否都符合表达式
            return datas.All(entity => predicate(entity));
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, ResDaprPlus.Format_DataAuth_CheckError, typeof(T).Name);
            // 发生错误时默认拒绝访问
            return false;
        }
    }
}
